package com.nbcio.im.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nbcio.common.core.utils.StringUtils;
import com.nbcio.im.core.ImMessage;
import com.nbcio.im.core.mapper.ImMessageMapper;
import com.nbcio.im.core.service.ImMessageService;
import com.nbcio.im.core.service.ImUserService;
import com.nbcio.system.domain.vo.SysUserVo;
import com.nbcio.im.core.service.ImGroupService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * IM消息服务实现
 *
 * @author nbacheng
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ImMessageServiceImpl extends ServiceImpl<ImMessageMapper, ImMessage> implements ImMessageService {
    
    private final ImUserService imUserService;
    private final ImGroupService imGroupService;
    
    @Override
    public String sendPrivateMessage(Long fromUserId, Long toUserId, String content, String messageType) {
        try {
            log.info("开始发送私聊消息: {} -> {}, 内容: {}", fromUserId, toUserId, content);
            
            // 验证用户是否存在
            SysUserVo fromUser = imUserService.getSysUser(fromUserId);
            if (fromUser == null) {
                log.error("发送者用户不存在: {}", fromUserId);
                throw new RuntimeException("发送者用户不存在");
            }
            log.info("发送者用户信息: {}", fromUser.getUserName());
            
            SysUserVo toUser = imUserService.getSysUser(toUserId);
            if (toUser == null) {
                log.error("接收者用户不存在: {}", toUserId);
                throw new RuntimeException("接收者用户不存在");
            }
            log.info("接收者用户信息: {}", toUser.getUserName());
            
            // 创建消息
            ImMessage message = new ImMessage();
            message.setMessageId(UUID.randomUUID().toString());
            message.setTenantId("000000"); // 默认租户ID
            message.setFromUserId(fromUserId);
            message.setToUserId(toUserId);
            message.setContent(content);
            message.setMessageType(messageType);
            message.setStatus("sent");
            message.setCreateTime(LocalDateTime.now());
            message.setIsRead(0);
            message.setIsRevoked(0);
            message.setSource("user");
            
            log.info("创建消息对象: messageId={}, fromUserId={}, toUserId={}, content={}", 
                    message.getMessageId(), message.getFromUserId(), message.getToUserId(), message.getContent());
            
            // 保存消息
            try {
                boolean saveResult = save(message);
                log.info("保存消息结果: {}", saveResult);
                
                if (!saveResult) {
                    log.error("保存消息失败");
                    throw new RuntimeException("保存消息失败");
                }
            } catch (Exception saveException) {
                log.error("保存消息时发生异常: {}", saveException.getMessage(), saveException);
                throw saveException;
            }
            
            // 发送WebSocket消息
            try {
                sendWebSocketMessage(message);
                log.info("WebSocket消息发送完成");
            } catch (Exception wsException) {
                log.warn("WebSocket消息发送失败，但消息已保存: {}", wsException.getMessage());
            }
            
            log.info("发送私聊消息成功: {} -> {}, 消息ID: {}", fromUserId, toUserId, message.getMessageId());
            return message.getMessageId();
        } catch (Exception e) {
            log.error("发送私聊消息失败: {} -> {}, 错误: {}", fromUserId, toUserId, e.getMessage(), e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String sendGroupMessage(Long fromUserId, String groupId, String content, String messageType) {
        // 验证群组是否存在
        if (imGroupService.getById(groupId) == null) {
            throw new RuntimeException("群组不存在");
        }
        
        // 验证用户是否在群组中
        if (!imGroupService.isMember(groupId, fromUserId)) {
            throw new RuntimeException("用户不在群组中");
        }
        
        // 创建消息
        ImMessage message = new ImMessage();
        message.setMessageId(UUID.randomUUID().toString());
        message.setTenantId("000000"); // 默认租户ID
        message.setFromUserId(fromUserId);
        message.setGroupId(groupId);
        message.setContent(content);
        message.setMessageType(messageType);
        message.setStatus("sent");
        message.setCreateTime(LocalDateTime.now());
        message.setIsRead(0);
        message.setIsRevoked(0);
        message.setSource("user");
        
        // 保存消息
        save(message);
        
        // 发送WebSocket消息
        sendWebSocketMessage(message);
        
        log.info("发送群组消息: {} -> {}, 内容: {}", fromUserId, groupId, content);
        return message.getMessageId();
    }
    
    @Override
    public List<ImMessage> getPrivateMessageHistory(Long userId1, Long userId2, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.eq(ImMessage::getFromUserId, userId1).eq(ImMessage::getToUserId, userId2)
                .or()
                .eq(ImMessage::getFromUserId, userId2).eq(ImMessage::getToUserId, userId1))
                .eq(ImMessage::getTenantId, "000000") // 添加租户ID过滤
                .orderByDesc(ImMessage::getCreateTime);
        
        Page<ImMessage> page = new Page<>(pageNum, pageSize);
        IPage<ImMessage> result = page(page, wrapper);
        
        log.info("查询消息历史: userId1={}, userId2={}, 查询到{}条消息", userId1, userId2, result.getRecords().size());
        return result.getRecords();
    }
    
    @Override
    public List<ImMessage> getPrivateConversations(Long userId) {
        // 先查询用户参与的所有私聊消息
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.eq(ImMessage::getFromUserId, userId)
                .or()
                .eq(ImMessage::getToUserId, userId))
                .isNull(ImMessage::getGroupId)
                .eq(ImMessage::getTenantId, "000000")
                .orderByDesc(ImMessage::getCreateTime);
        
        List<ImMessage> allMessages = list(wrapper);
        
        // 按会话分组，获取每个会话的最新消息
        Map<Long, ImMessage> latestMessages = new HashMap<>();
        for (ImMessage message : allMessages) {
            Long otherUserId = message.getFromUserId().equals(userId) ? 
                message.getToUserId() : message.getFromUserId();
            
            if (!latestMessages.containsKey(otherUserId) || 
                message.getCreateTime().isAfter(latestMessages.get(otherUserId).getCreateTime())) {
                latestMessages.put(otherUserId, message);
            }
        }
        
        List<ImMessage> result = new ArrayList<>(latestMessages.values());
        result.sort((a, b) -> b.getCreateTime().compareTo(a.getCreateTime()));
        
        log.info("查询私聊会话: userId={}, 查询到{}个会话", userId, result.size());
        return result;
    }
    
    @Override
    public int getUnreadCount(Long userId, Long toUserId, String groupId) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getTenantId, "000000");
        
        if (toUserId != null) {
            // 私聊未读消息：对方发给我的消息，且我未读
            wrapper.and(w -> w.eq(ImMessage::getFromUserId, toUserId).eq(ImMessage::getToUserId, userId))
                   .isNull(ImMessage::getGroupId)
                   .eq(ImMessage::getIsRead, 0);
        } else if (groupId != null) {
            // 群聊未读消息：群聊中的消息，且我未读
            wrapper.eq(ImMessage::getGroupId, groupId)
                   .ne(ImMessage::getFromUserId, userId) // 排除自己发送的消息
                   .eq(ImMessage::getIsRead, 0);
        } else {
            return 0;
        }
        
        long count = count(wrapper);
        log.debug("查询未读消息数: userId={}, toUserId={}, groupId={}, count={}", 
                 userId, toUserId, groupId, count);
        return (int) count;
    }
    
    @Override
    public int markAsRead(Long userId, Long toUserId, String groupId) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getTenantId, "000000");
        
        if (toUserId != null) {
            // 私聊消息：对方发给我的消息，且我未读
            wrapper.and(w -> w.eq(ImMessage::getFromUserId, toUserId).eq(ImMessage::getToUserId, userId))
                   .isNull(ImMessage::getGroupId)
                   .eq(ImMessage::getIsRead, 0);
        } else if (groupId != null) {
            // 群聊消息：群聊中的消息，且我未读
            wrapper.eq(ImMessage::getGroupId, groupId)
                   .ne(ImMessage::getFromUserId, userId) // 排除自己发送的消息
                   .eq(ImMessage::getIsRead, 0);
        } else {
            return 0;
        }
        
        // 批量更新为已读
        ImMessage updateMessage = new ImMessage();
        updateMessage.setIsRead(1);
        // 暂时注释掉readTime，因为数据库表中还没有这个字段
        // updateMessage.setReadTime(java.time.LocalDateTime.now());
        
        boolean result = update(updateMessage, wrapper);
        long count = count(wrapper);
        
        log.info("标记消息已读: userId={}, toUserId={}, groupId={}, 更新数量={}", 
                userId, toUserId, groupId, count);
        return (int) count;
    }
    
    @Override
    public List<ImMessage> getGroupMessageHistory(String groupId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getGroupId, groupId)
                .orderByDesc(ImMessage::getCreateTime);
        
        Page<ImMessage> page = new Page<>(pageNum, pageSize);
        IPage<ImMessage> result = page(page, wrapper);
        return result.getRecords();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAsRead(String messageId, Long userId) {
        ImMessage message = getById(messageId);
        if (message != null && !message.getFromUserId().equals(userId)) {
            message.setIsRead(1);
            updateById(message);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean revokeMessage(String messageId, Long userId) {
        ImMessage message = getById(messageId);
        if (message != null && message.getFromUserId().equals(userId)) {
            // 检查是否超过撤回时间限制（2分钟）
            if (message.getCreateTime().isAfter(LocalDateTime.now().minusMinutes(2))) {
                message.setIsRevoked(1);
                message.setRevokeTime(LocalDateTime.now());
                updateById(message);
                
                // 发送撤回通知
                sendRevokeNotification(message);
                return true;
            }
        }
        return false;
    }
    
    @Override
    public Integer getUnreadCount(Long userId) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getToUserId, userId)
                .eq(ImMessage::getIsRead, false)
                .eq(ImMessage::getIsRevoked, false);
        return Math.toIntExact(count(wrapper));
    }
    
    @Override
    public Integer getUnreadCount(Long userId, Long targetUserId) {
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getFromUserId, targetUserId)
                .eq(ImMessage::getToUserId, userId)
                .eq(ImMessage::getIsRead, false)
                .eq(ImMessage::getIsRevoked, false);
        return Math.toIntExact(count(wrapper));
    }
    
    @Override
    public Integer getGroupUnreadCount(Long userId, String groupId) {
        // 获取用户加入群组的时间
        LocalDateTime joinTime = imGroupService.getJoinTime(groupId, userId);
        if (joinTime == null) {
            return 0;
        }
        
        LambdaQueryWrapper<ImMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImMessage::getGroupId, groupId)
                .ne(ImMessage::getFromUserId, userId)
                .gt(ImMessage::getCreateTime, joinTime)
                .eq(ImMessage::getIsRevoked, false);
        return Math.toIntExact(count(wrapper));
    }
    
    /**
     * 发送WebSocket消息
     */
    private void sendWebSocketMessage(ImMessage message) {
        try {
            // 这里集成WebSocket发送逻辑
            // 可以通过现有的WebSocket服务发送消息
            log.debug("发送WebSocket消息: {}", message.getMessageId());
            
            // 如果是群聊消息，通过ImService发送
            if (StringUtils.isNotBlank(message.getGroupId())) {
                // 群聊消息的WebSocket推送在ImService中处理
                log.debug("群聊消息WebSocket推送由ImService处理: {}", message.getMessageId());
            } else {
                // 私聊消息的WebSocket推送在ImService中处理
                log.debug("私聊消息WebSocket推送由ImService处理: {}", message.getMessageId());
            }
        } catch (Exception e) {
            log.error("发送WebSocket消息失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 发送撤回通知
     */
    private void sendRevokeNotification(ImMessage message) {
        // 发送撤回通知的WebSocket消息
        log.debug("发送撤回通知: {}", message.getMessageId());
    }
}
